home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / DDJMAG / DDJ9212.ZIP / beaut.asc < prev    next >
Text File  |  1992-11-30  |  8KB  |  260 lines

  1. _A C++ BEAUTIFIER_
  2. by Tim Maher
  3.  
  4. [LISTING 1]
  5.  
  6.    1  :
  7.    2  #    @(#) c++cb,c++indent - driver program for C++ beautification
  8.    3  #    Tim Maher, CONSULTIX, 11/9/91.    (206) 781-UNIX
  9.    4  #
  10.    5  ENCODED=/tmp/c++encode_$$      BEAUT=/tmp/beaut_$$    # temp files
  11.    6  case "$0"    in  # use cb or    indent,    depending on invocation    name
  12.    7  *c++cb)    OUT=""        # for cb, all arguments are    optional
  13.    8    while    test $#    -gt 0    # separate options from    filenames
  14.    9    do  case "$1" in    # "l" option takes argument
  15.   10        -[!l])  OPTS="$OPTS    $1"; shift ;;
  16.   11        -l)        OPTS="$OPTS    $1 $2";    shift 2    ;;
  17.   12        *)        break    # end of options
  18.   13        esac
  19.   14    done # if no filename, copy stdin, and set filename arg
  20.   15    test -z    "$*" &&    cat > /tmp/c++cb_$$ && set /tmp/c++cb_$$
  21.   16    BEAUTIFY="cb $OPTS $ENCODED > $BEAUT"; INPUT=$*    ;;
  22.   17  *c++indent)    # not a    filter;    needs filename arg
  23.   18    INPUT=${1:?"Usage: $0 infile [outfile] [flags]"}; shift
  24.   19    case "$1" in    # next arg would be output filename or flag
  25.   20    "") ;;        # no second arg    is okay    too
  26.   21    [!-]*)    OUT=$1;    shift    # set output filename
  27.   22    esac
  28.   23    OPTS="$*"; : ${OUT:=$INPUT} # if no outfile, use input name
  29.   24     BEAUTIFY="indent $ENCODED $BEAUT $OPTS    -Tasm -Tbool -Tcatch
  30.   25    -Tclass    -Tconst    -Tdelete -Tdo -Tfriend -Tinline    -Tnew
  31.   26    -Tprivate -Tprotected -Tpublic -Tsigned    -Ttemplate -Tthrow
  32.   27    -Ttry -Tvirtual    -Tvolatile"    # -Toperator omitted
  33.   28  esac
  34.   29  :    ${CppSYM:=_42};    export CppSYM;    # set up disguising string
  35.   30  name=`grep -l "$CppSYM" $INPUT` &&    # exit if symbol in    input
  36.   31    { echo Error- \"$CppSYM\" appears in $name >&2;    exit 100; }
  37.   32  c++encode    $INPUT > $ENCODED || exit 100
  38.   33  if    eval $BEAUTIFY    # beautify, leaving output in $BEAUT
  39.   34  then  trap "" 2 3    15; # reconstruct C++ after beautification
  40.   35    sed -e 's+/\*-\(.*\) -\*/$+//\1+' -e "s/_${CppSYM}_/ : /g" \
  41.   36        -e "s/$CppSYM/::/g"    < $BEAUT > $OUT
  42.   37  else  echo "$0: error code $? from $BEAUTIFY" >&2; exit 200
  43.   38  fi
  44.   39  rm -f /tmp/*_$$; # clean-up temp files
  45.  
  46.  
  47.  
  48. [LISTING 2]
  49.  
  50.   1  /*    @(#) c++encode.c: Tim Maher, 11/9/91,  tim@Timji.Celestial.Com
  51.   2    C++ syntax disguiser, allowing beautification via cb, indent */
  52.   3  #include <stdio.h>
  53.   4  #include <string.h>    /* Use this line for AT&T systems */
  54.   5  /*    #include <strings.h>    /* Use this line for BSD systems */
  55.   6  char *getenv();
  56.   7  #define MAX 512    /* Maximum length for C++ input    line */
  57.   8  #define F    0   /* FALSE */
  58.   9  #define T    1   /* TRUE */
  59.  10
  60.  11  main (argc, argv) int argc; char *argv[]; {
  61.  12    int filenum, linenum, cnum, modes, exit();
  62.  13    int sq,    dq, cc,    ic, ch,    nx, max, knt;
  63.  14    char    line[MAX], out[10], *sym;
  64.  15    FILE    *handle;
  65.  16
  66.  17    if (argc < 2) {
  67.  18        fprintf(stderr, "Usage: %s file1 [file2 . .    .]\n",
  68.  19        argv[0]);  exit(1);
  69.  20    }
  70.  21    /* use default "sym" string if none supplied */
  71.  22    if ((sym=getenv("CppSYM")) == (char *)0) sym="_42";
  72.  23    for (filenum = 1; filenum < argc; filenum++) {
  73.  24        handle = (filenum == 1 ? fopen(argv[filenum], "r") :
  74.  25        freopen(argv[filenum], "r", handle));
  75.  26         if    (handle    == (FILE *)0) {
  76.  27        fprintf(stderr,    "%s: fopen() error\n",argv[0]);
  77.  28        exit (50);
  78.  29        }
  79.  30        linenum = 0; sq = dq = cc =    ic = F;
  80.  31        while (fgets(line, MAX, handle) != (char *)    0) {
  81.  32        max=strlen(line)-2; /* ignore NL; 0-based index    */
  82.  33        if (max    == MAX - 3) {
  83.  34            fprintf(stderr,"%s:    increase MAX\n", argv[0]);
  84.  35            exit(100);
  85.  36        }
  86.  37        linenum++;
  87.  38        for (cnum = 0; cnum <= max; cnum++) {
  88.  39            ch = line[cnum];
  89.  40            sprintf(out,"%c",ch);   /* default out = ch    */
  90.  41            nx = (cnum == max) ? '\0' :    line[cnum+1];
  91.  42            if (cc) {    /* in C    comment    mode */
  92.  43            if ('*'    == ch && nx == '/') {
  93.  44                /* C comment ends */
  94.  45                cc = F; strcpy(out,    "*/"); cnum++;
  95.  46            }
  96.  47            } else if ('/' == ch && nx == '*' && !(sq||dq)) {
  97.  48            /* C comment starts */
  98.  49            cc = T;    strcpy(out, "/*"); cnum++;
  99.  50            } else if (ic) ;    /* in inline comment */
  100.  51            else if ('/' == ch && nx ==    '/' && !sq && !dq) {
  101.  52            /* inline comment starts */
  102.  53            ic = T;    sprintf(out, "/*-"); cnum++;
  103.  54             } else if ('\\' ==    ch) {     /* quote by BS    */
  104.  55            if (cnum != max) {  /* next char is quoted */
  105.  56                sprintf(out, "%c%c", ch, nx); cnum++;
  106.  57            }
  107.  58            } else if (dq) {        /* in double-quotes    */
  108.  59            if ('"'    == ch)     dq = F; /* DQ string ends */
  109.  60            } else if (sq) {        /* in single-quotes    */
  110.  61            if (ch    == '\'') sq = F; /* SQ string ends */
  111.  62            } else if ('\'' == ch) sq =    T;  /* SQ starts */
  112.  63            else if ('"'  == ch) dq = T;    /* DQ starts */
  113.  64            else strcpy(out,"");    /* no output created */
  114.  65            /* OUTPUT OF QUOTED    AND COMMENTED TEXT */
  115.  66            if (strcmp(out,"") != 0) {    /* non-null string */
  116.  67            /* print and then process next char */
  117.  68            printf("%s", out); continue;
  118.  69            } /* PROCESS UNQUOTED AND UNCOMMENTED TEXT */
  119.  70            /* process scope qualifier;    :: -> sym */
  120.  71            if (ch == ':' && nx    == ':')    {
  121.  72            strcpy(out, sym); cnum++;
  122.  73            } else if (ch == ' ' && nx == ':') {
  123.  74            /* handle derivation; SP:SP OR SP:NL */
  124.  75            if (cnum == max) {  /* line ends with :    */
  125.  76                sprintf(out, "%s%s%s", "_",    sym, "_");
  126.  77                cnum += 1;    /* SP:NL -> _sym_NL */
  127.  78            } else if (line[cnum+2]    == ' ')    {
  128.  79                sprintf(out, "%s%s%s", "_",    sym, "_");
  129.  80                cnum += 2;    /* SP:SP -> _sym_ */
  130.  81            }
  131.  82             } /* FOLLOWING SECTION DOES ALL NORMAL OUTPUT */
  132.  83            /* print prepared string, or literal input ch */
  133.  84            if (strcmp(out, "")    != 0)    printf("%s", out);
  134.  85            else            printf("%c", ch);
  135.  86        }   /* END OF FOR-CNUM LOOP; FINISHED WITH LINE    */
  136.  87        if (ic)    {   /* inlines end with    EOL, so    turn off */
  137.  88            ic = F; printf(" -*/\n");
  138.  89        } else    printf("\n");    /* NL to end this line */
  139.  90        } /* END OF    WHILE LOOP */
  140.  91        if (sq || dq || ic || cc) {
  141.  92        fprintf(stderr,"%s: %s%s; sq=%d    dq=%d ic=%d cc=%d\n",
  142.  93        argv[0], "ERROR- altered mode at EOF for file ",
  143.  94        argv[filenum], sq,dq,ic,cc); exit (200);
  144.  95        }
  145.  96    }   /* END OF FOR FILENUM LOOP */
  146.  97    exit (0);
  147.  98  }
  148.  
  149.  
  150. Example 1:
  151.  
  152. (a) 
  153. $ cat sample.cc
  154.  
  155.    1  class C : virtual public F { public:
  156.    2  C(int x):F(x, 100u) { } // note; arg 2: unsigned
  157.    3  C func(double* = 0);  /* defined below */
  158.    4  };
  159.    5  C C::func(double*x) { if (x)  // commentary
  160.    6  { } // inline comment with funny stuff- // : ::
  161.    7  }
  162.  
  163. (b) 
  164. $ cb sample.cc
  165.  
  166.    1  class C :
  167.    2  virtual public F {
  168.    3  public:
  169.    4    C(int x):
  170.    5    F(x, 100u) {
  171.    6    }
  172.    7     / / note;
  173.    8  arg 2:
  174.    9    unsigned
  175.   10    C func(double * = 0);   /* defined below */
  176.   11  };
  177.   12
  178.   13
  179.   14  C C:
  180.   15  :
  181.   16  func(double*x)
  182.   17  {
  183.   18    if (x)
  184.   19         / / commentary
  185.   20         {
  186.   21        }
  187.   22   / / inline comment with funny stuff - / / :
  188.   23  :
  189.   24  :
  190.   25  }
  191.   26
  192.   27
  193.  
  194. (c) 
  195. $ c++encode sample.cc
  196.  
  197.    1  class C__42_virtual public F { public:
  198.    2  C(int x):F(x, 100u) { } /*- note; arg 2: unsigned -*/
  199.    3  C func(double* = 0);  /* defined below */
  200.    4  };
  201.    5  C C_42func(double*x) { if (x) /*- commentary -*/
  202.    6  { } /*- inline comment with funny stuff- // : :: -*/
  203.    7  }
  204.  
  205.  
  206. (d)
  207. $ c++cb sample.cc
  208.  
  209.    1  class C : virtual public F {
  210.    2  public:
  211.    3    C(int x):
  212.    4    F(x, 100u) {
  213.    5    } // note; arg 2: unsigned
  214.    6    C func(double* = 0);    /* defined below */
  215.    7  };
  216.    8  C C::func(double*x) {
  217.  
  218.    9   if (x)  // commentary
  219.   10    {
  220.   11    } // inline comment with funny stuff- // : ::
  221.   12  }
  222.  
  223. (e) 
  224. $ c++cb -s sample.cc
  225.  
  226.    1  class C : virtual public F {
  227.    2  public:
  228.    3    C(int x):
  229.    4    F(x, 100u) {
  230.    5    } // note; arg 2: unsigned
  231.    6    C func(double * = 0);   /* defined below */
  232.    7  };
  233.    8
  234.    9
  235.   10  C C::func(double*x)
  236.   11  {
  237.   12    if (x)  /*- commentary -*/ {
  238.   13    } // inline comment with funny stuff- // : ::
  239.   14  }
  240.   15
  241.   16
  242.  
  243. (f)
  244. $ c++indent sample.cc; cat sample.cc
  245.  
  246.    1  class C : virtual public F {
  247.    2    public:
  248.    3            C(int x):F(x, 100 u) {
  249.    4    }       // note; arg 2: unsigned
  250.    5    C       func(double *= 0);  /* defined below */
  251.    6  };
  252.    7  C
  253.    8  C::func(double *x)
  254.    9  {
  255.   10    if (x) {    // commentary
  256.   11    }       // inline comment with funny stuff- // : ::
  257.   12  }
  258.  
  259.  
  260.